package com.jtbd.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.jtbd.client.JtbdRedisClient;
import com.jtbd.client.ObjectMapperClient;
import com.jtbd.domain.UserEmployee;
import com.jtbd.domain.UserInfo;
import com.jtbd.domain.UserStudent;
import com.jtbd.dto.JwtSimplePayloadEntity;
import com.jtbd.dto.db.UserEmployeeInfo;
import com.jtbd.dto.db.UserStudentInfo;
import com.jtbd.utils.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

@Component
public class UserLoginInfoHandler {
    private final String REDIS_TOKEN_KEY_PREFIX = "login:token:";
    private final String REDIS_USER_KEY_PREFIX = "user:info:";
    private final String REDIS_STUDENT_KEY_PREFIX = "user:student:";
    private final String REDIS_EMPLOYEE_KEY_PREFIX = "user:employee:";

    @Resource
    private JtbdRedisClient redisClient;
    @Resource
    private JwtUtil jwtUtil;


    /**
     * 学生登录处理函数
     *
     * @param userStudentInfo 学生用户信息对象，包含用户基本信息和学生特定信息
     * @param response        HTTP响应对象，用于设置响应头
     * @return 登录处理结果，成功返回true
     * @throws RuntimeException 当JWT令牌生成或Redis操作异常时抛出运行时异常
     */
    public boolean studentLogin(UserStudentInfo userStudentInfo, HttpServletResponse response) {
        try {
            // 生成JWT令牌并存储到Redis中，同时设置响应头
            String token = jwtUtil.generateToken(new JwtSimplePayloadEntity(userStudentInfo.getUserInfo().getId()));
            redisClient.set(REDIS_TOKEN_KEY_PREFIX + userStudentInfo.getUserInfo().getId(), token);
            response.setHeader(JwtUtil.JWT_KEY, token);

            // 将用户信息和学生信息序列化后存储到Redis中
            redisClient.set(REDIS_USER_KEY_PREFIX + userStudentInfo.getUserInfo().getId(), ObjectMapperClient.writeValue(userStudentInfo.getUserInfo()));
            redisClient.set(REDIS_STUDENT_KEY_PREFIX + userStudentInfo.getUserInfo().getId(), ObjectMapperClient.writeValue(userStudentInfo.getUserStudent()));
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据用户ID获取学生信息
     *
     * @param uid 用户ID
     * @return 用户学生信息对象，包含用户基本信息和学生详细信息
     * @throws RuntimeException 当JSON解析失败时抛出运行时异常
     */
    public UserStudentInfo getStudentInfo(Long uid) {
        try {
            // 从Redis中获取用户基本信息和学生信息的JSON字符串
            String base = redisClient.get(REDIS_USER_KEY_PREFIX + uid);
            String student = redisClient.get(REDIS_STUDENT_KEY_PREFIX + uid);

            // 将JSON字符串反序列化为对应的对象
            UserInfo userInfo = ObjectMapperClient.readValue(base, UserInfo.class);
            UserStudent userStudent = ObjectMapperClient.readValue(student, UserStudent.class);

            // 构造并返回包含用户信息和学生信息的复合对象
            return new UserStudentInfo(userInfo, userStudent);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 员工登录处理函数
     *
     * @param userEmployeeInfo 用户员工信息对象，包含用户基本信息和员工详细信息
     * @param response         HTTP响应对象，用于设置响应头
     * @return 登录处理结果，成功返回true，失败抛出异常
     */
    public boolean employeeLogin(UserEmployeeInfo userEmployeeInfo, HttpServletResponse response) {
        try {
            // 生成JWT令牌并存储到Redis中，同时设置到响应头中
            String token = jwtUtil.generateToken(new JwtSimplePayloadEntity(userEmployeeInfo.getUserInfo().getId()));
            redisClient.set(REDIS_TOKEN_KEY_PREFIX + userEmployeeInfo.getUserInfo().getId(), token);
            response.setHeader(JwtUtil.JWT_KEY, token);

            // 将用户信息和员工信息序列化后存储到Redis中
            redisClient.set(REDIS_USER_KEY_PREFIX + userEmployeeInfo.getUserInfo().getId(), ObjectMapperClient.writeValue(userEmployeeInfo.getUserInfo()));
            redisClient.set(REDIS_EMPLOYEE_KEY_PREFIX + userEmployeeInfo.getUserInfo().getId(), ObjectMapperClient.writeValue(userEmployeeInfo.getUserEmployee()));
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据用户ID获取用户员工信息
     *
     * @param uid 用户ID
     * @return 用户员工信息对象，包含用户基本信息和员工信息
     * @throws RuntimeException 当Redis访问异常或数据解析异常时抛出
     */
    public UserEmployeeInfo getUserEmployeeInfo(Long uid) {
        try {
            // 从Redis中获取用户基本信息和员工信息
            String base = redisClient.get(REDIS_USER_KEY_PREFIX + uid);
            String employee = redisClient.get(REDIS_EMPLOYEE_KEY_PREFIX + uid);

            // 将JSON字符串转换为对应的对象
            UserInfo userInfo = ObjectMapperClient.readValue(base, UserInfo.class);
            UserEmployee userEmployee = ObjectMapperClient.readValue(employee, UserEmployee.class);

            // 构造并返回用户员工信息对象
            return new UserEmployeeInfo(userEmployee, userInfo);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 用户登出操作
     * 清除用户在Redis中的相关缓存数据
     *
     * @param uid 用户唯一标识符
     */
    public void logout(Long uid) {
        // 删除用户的登录token缓存
        redisClient.delete("login:token:" + uid);
        // 删除用户基本信息缓存
        redisClient.delete("user:info:" + uid);
        // 删除用户学生信息缓存
        redisClient.delete("user:student:" + uid);
        // 删除用户员工信息缓存
        redisClient.delete("user:employee:" + uid);
    }

}
